package com.yunmaozj.tools.site.server.util;

import com.yunmaozj.tools.site.server.dto.Developer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.bean.BeanElement;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.dom4j.tree.DefaultElement;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.util.List;

import static java.util.Objects.isNull;

/**
 * @author zhongminghong
 * @email zhongmh@yunmaozj.com
 * @create 2022-05-26 23:40
 */
@Slf4j
public class DocumentMetadata {

    private File metaDataFile;
    private Document document;

    private DocumentMetadata(File metaDataFile, Document document) {
        this.document = document;
        this.metaDataFile = metaDataFile;
    }

    public void addDeveloper(List<Developer> developerList) {
        Element projectElement = document.getRootElement();
        Element developersElement = projectElement.element("developers");
        if (isNull(developersElement)) {
            developersElement = projectElement.addElement("developers");
        }
        List<Element> developerElementList = developersElement.elements("developer");
        developerElementList.forEach(developersElement::remove);
        for (Developer developer : developerList) {
            developersElement.add(buildDeveloper(developer));
        }
        writeMetadataFile(metaDataFile, document);
    }

    public Element buildDeveloper(Developer developer) {
        Element element = new DefaultElement("developer");
        element.add(new DefaultElement("id") {{
            setText(developer.getId());
        }});
        element.add(new DefaultElement("name") {{
            setText(developer.getName());
        }});
        if (StringUtils.isNotEmpty(developer.getUrl())) {
            element.add(new DefaultElement("email") {{
                setText(developer.getEmail());
            }});
        }
        if (StringUtils.isNotEmpty(developer.getUrl())) {
            element.add(new DefaultElement("url") {{
                setText(developer.getUrl());
            }});
        }
        element.addAttribute("lastUpdateTime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        return element;
    }

    public static DocumentMetadata load(FileManager fileManager, String projectId) throws DocumentException {
        File projectDirectory = fileManager.getProjectDirectory(projectId);
        String metadataFileName = "project-metadata.xml";
        File metadataFile = new File(projectDirectory, metadataFileName);
        if (!metadataFile.exists()) {
            initProjectMetadata(metadataFile);
        }
        SAXReader reader = new SAXReader();
        Document document = reader.read(metadataFile);
        return new DocumentMetadata(metadataFile, document);
    }

    private static void initProjectMetadata(File metadataFile) {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("project");
        root.addAttribute("addTime", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        writeMetadataFile(metadataFile, doc);
    }

    private static void writeMetadataFile(File metadataFile, Document document) {
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        Writer out = null;
        try {
            out = new FileWriter(metadataFile);
            XMLWriter writer = new XMLWriter(out, format);
            writer.write(document);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(out);
        }
    }
}
